package evolution.tests;

import java.lang.reflect.Method;

import org.junit.Assert;
import org.junit.Test;

import evolution.individual.FitnessFunctionIndividualsFactory;
import evolution.operation.reproduction.AMXOReproduction;
import evolution.problem.RastriginMinimization;
import evolution.random.SFMT19937RandomGen;

public class ReproductionTest {

	/**
	 * Arithmetic crossover method (AMXO) Test. Parent1 : [1, 2, 3] Parent2 :
	 * [4, 6, 8] const a = 0.2 Desc1[0] = a*Parent1[0] + (1-a)*Parent2[0]
	 * Desc1[0] = 0.2*1 + 0.8*4 = 0.2 + 3.2 = 3,4 Desc1 = [3.4, 5.2, 7.0]
	 * 
	 * Desc2[0] = a*Parent2[0] + (1-a)*Parent1[0] Desc2[0] = 0.2*4 + 0.8*1 =
	 * 0.8+0.8 = 1.6 Desc2 = [1.6, 2.8, 4.0]
	 */
	@Test
	public void AMXOTest() {
		try {
			double[] parent1 = { 1.0, 2.0, 3.0 };
			double[] parent2 = { 4.0, 6.0, 8.0 };
			double a = 0.2;
			double[] desc1 = new double[3];
			double[] desc2 = new double[3];
			double[] expectDesc1 = { 3.4, 5.2, 7.0 };
			double[] expectDesc2 = { 1.6, 2.8, 4.0 };

			SFMT19937RandomGen sfmt19937RandomGen = new SFMT19937RandomGen();

			AMXOReproduction repClass = new AMXOReproduction();
			repClass.setIndividualsFactory(new FitnessFunctionIndividualsFactory(
					new RastriginMinimization().getFitnessFunction()));
			repClass.setRandomGenerator(sfmt19937RandomGen);

			Method crossing = AMXOReproduction.class.getDeclaredMethod(
					"crossing", double[].class, double[].class, double[].class,
					double[].class, double.class);
			crossing.setAccessible(true);
			crossing.invoke(repClass, parent1, parent2, desc1, desc2, a);

			Assert.assertArrayEquals(expectDesc1, desc1, 0.001);
			Assert.assertArrayEquals(expectDesc2, desc2, 0.001);
		} catch (Exception e) {
			e.printStackTrace();
			Assert.fail();
		}
	}
}
